package com.supor.aiot.common.utils;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.MediaMetadataRetriever;
import android.widget.ImageView;

import com.alipay.mobile.beehive.capture.utils.Logger;
import com.android.baseconfig.common.utils.Logc;
import com.android.baseconfig.common.utils.StringUtils;
import com.android.baseconfig.common.utils.SystemUtils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import com.bumptech.glide.request.RequestOptions;
import com.supor.aiot.common.R;
import com.supor.aiot.common.app.AppAgent;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.MessageDigest;

import androidx.annotation.NonNull;

import static android.R.attr.path;
import static android.content.ContentValues.TAG;
import static com.bumptech.glide.load.resource.bitmap.VideoDecoder.FRAME_OPTION;

/**
 * ---------------------------------------------------------------- <br>
 * Copyright (C) 2014-2020, by het, Shenzhen, All rights reserved.  <br>
 * ---------------------------------------------------------------- <br>
 * <p>
 * 描述: BitmapUtil <br>
 * 作者: lei <br>
 * 日期: 2021/1/26 <br>
 */
public class BitmapUtil {


    public static RequestOptions options1 = new RequestOptions()
            .placeholder(R.drawable.shape_loading_rotate)    //加载成功之前占位图
            .error(R.mipmap.load_photo_fail)    //加载错误之后的错误图
            // .override(300, 300)    //指定图片的尺寸
            .fitCenter()   //指定图片的缩放类型为fitCenter
            // （等比例缩放图片，宽或者是高等于ImageView的宽或者是高。是指其中一个满足即可不会一定铺满imageview）
            .centerCrop()//指定图片的缩放类型为centerCrop （等比例缩放图片，直到图片的宽高都大于等于ImageView的宽度，然后截取中间的显示。）
            .skipMemoryCache(true)    //不使用内存缓存
            .diskCacheStrategy(DiskCacheStrategy.ALL)    //缓存所有版本的图像
            .diskCacheStrategy(DiskCacheStrategy.NONE)    //不使用硬盘本地缓存
            .diskCacheStrategy(DiskCacheStrategy.DATA)    //只缓存原来分辨率的图片
            .diskCacheStrategy(DiskCacheStrategy.RESOURCE)    //只缓存最终的图片
            ;
    /**
     * 指定图片的尺寸 300*300
     */
    public static RequestOptions options2 = new RequestOptions()
            .placeholder(R.drawable.shape_loading_rotate)    //加载成功之前占位图
            .error(R.mipmap.load_photo_fail)    //加载错误之后的错误图
            .override(300, 300)    //指定图片的尺寸
            .fitCenter()   //指定图片的缩放类型为fitCenter
            // （等比例缩放图片，宽或者是高等于ImageView的宽或者是高。是指其中一个满足即可不会一定铺满imageview）
            .centerCrop()//指定图片的缩放类型为centerCrop （等比例缩放图片，直到图片的宽高都大于等于ImageView的宽度，然后截取中间的显示。）
            .skipMemoryCache(true)    //不使用内存缓存
            .diskCacheStrategy(DiskCacheStrategy.ALL)    //缓存所有版本的图像
            .diskCacheStrategy(DiskCacheStrategy.NONE)    //不使用硬盘本地缓存
            .diskCacheStrategy(DiskCacheStrategy.DATA)    //只缓存原来分辨率的图片
            .diskCacheStrategy(DiskCacheStrategy.RESOURCE)    //只缓存最终的图片
            ;
    public static RequestOptions options3 = new RequestOptions()
            .placeholder(R.drawable.shape_loading_rotate)    //加载成功之前占位图
            .error(R.mipmap.load_photo_fail)    //加载错误之后的错误图
            .fitCenter()   //指定图片的缩放类型为fitCenter
            // （等比例缩放图片，宽或者是高等于ImageView的宽或者是高。是指其中一个满足即可不会一定铺满imageview）
            .skipMemoryCache(true)    //不使用内存缓存
            .diskCacheStrategy(DiskCacheStrategy.ALL)    //缓存所有版本的图像
            .diskCacheStrategy(DiskCacheStrategy.NONE)    //不使用硬盘本地缓存
            .diskCacheStrategy(DiskCacheStrategy.DATA)    //只缓存原来分辨率的图片
            .diskCacheStrategy(DiskCacheStrategy.RESOURCE)    //只缓存最终的图片
            ;

    // 不使用缓存
    public static RequestOptions options4 = new RequestOptions()
            .fitCenter()   //指定图片的缩放类型为fitCenter
            // （等比例缩放图片，宽或者是高等于ImageView的宽或者是高。是指其中一个满足即可不会一定铺满imageview）
            .centerCrop()//指定图片的缩放类型为centerCrop （等比例缩放图片，直到图片的宽高都大于等于ImageView的宽度，然后截取中间的显示。）
            .skipMemoryCache(true)    //不使用内存缓存
            .diskCacheStrategy(DiskCacheStrategy.NONE)    //不使用硬盘本地缓存
            ;

    // 使用缓存
    public static RequestOptions options5 = new RequestOptions()
            .error(R.mipmap.load_photo_fail)    //加载错误之后的错误图
            .fitCenter()   //指定图片的缩放类型为fitCenter
            // （等比例缩放图片，宽或者是高等于ImageView的宽或者是高。是指其中一个满足即可不会一定铺满imageview）
            .centerCrop()//指定图片的缩放类型为centerCrop （等比例缩放图片，直到图片的宽高都大于等于ImageView的宽度，然后截取中间的显示。）
            .skipMemoryCache(false)    //不使用内存缓存
            .diskCacheStrategy(DiskCacheStrategy.ALL)    //缓存所有版本的图像
            ;

    //bitmap中的透明色用白色替换
    public static Bitmap changeColor(Bitmap bitmap) {
        if (bitmap == null) {
            return null;
        }
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        int[] colorArray = new int[w * h];
        int n = 0;
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                int color = getMixtureWhite(bitmap.getPixel(j, i));
                colorArray[n++] = color;
            }
        }
        return Bitmap.createBitmap(colorArray, w, h, Bitmap.Config.ARGB_8888);
    }

    //获取和白色混合颜色
    private static int getMixtureWhite(int color) {
        int alpha = Color.alpha(color);
        int red = Color.red(color);
        int green = Color.green(color);
        int blue = Color.blue(color);
        return Color.rgb(getSingleMixtureWhite(red, alpha), getSingleMixtureWhite(green, alpha),
                getSingleMixtureWhite(blue, alpha));
    }

    // 获取单色的混合值
    private static int getSingleMixtureWhite(int color, int alpha) {
        int newColor = color * alpha / 255 + 255 - alpha;
        return Math.min(newColor, 255);
    }

    /**
     * @param context 上下文
     * @param uri 视频地址
     * @param imageView 设置image
     * @param frameTimeMicros 获取某一时间帧
     */
    @SuppressLint("CheckResult")
    public static void loadVideoScreenshot(Context context, String uri, ImageView imageView, long frameTimeMicros) {
        RequestOptions requestOptions = RequestOptions.frameOf(frameTimeMicros);
        requestOptions.set(FRAME_OPTION, MediaMetadataRetriever.OPTION_CLOSEST);
        if (context == null) {
            context = AppAgent.getApp();
        }
        Context finalContext = context;
        requestOptions.transform(new BitmapTransformation() {
            @Override
            protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
                return toTransform;
            }

            @Override
            public void updateDiskCacheKey(MessageDigest messageDigest) {
                try {
                    messageDigest.update((finalContext.getPackageName() + "RotateTransform").getBytes("utf-8"));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        Glide.with(context)
                .load(uri)
                .apply(requestOptions)
                .into(imageView);
    }

    public static void loadUrl(Context context, final String url, final ImageView imageView, RequestOptions options) {

        if (context == null) {
            context = AppAgent.getApp();
        }
        if (options == null) {
            options = BitmapUtil.options1;
        }
        Glide.with(context)
                .load(url)
                .apply(options)
                .into(imageView);
    }

    public static void loadUrl(final String url, final ImageView imageView, RequestOptions options) {
        loadUrl(null, url, imageView, options);
    }

    public static void loadUrl(Context context, final String url, final ImageView imageView) {
        loadUrl(context, url, imageView, null);
    }

    public static void loadUrl(final String url, final ImageView imageView) {
        loadUrl(null, url, imageView, null);
    }

    public static void loadLocal(Context context, final File file, final ImageView imageView, RequestOptions options) {
        if (!file.exists()) {
            Logc.e(TAG, "invalid parameters absPath " + path);
            imageView.setImageResource(R.mipmap.load_photo_fail);
            return;
        }
        if (context == null) {
            context = AppAgent.getApp();
        }
        if (options == null) {
            options = BitmapUtil.options1;
        }
        Glide.with(context)
                .load(file)
                .apply(options)
                .into(imageView);
    }

    public static void loadLocal(final File file, final ImageView imageView, RequestOptions options) {
        loadLocal(null, file, imageView, options);
    }

    public static void loadLocal(final String path, final ImageView imageView, RequestOptions options) {
        final File file = new File(path);
        loadLocal(file, imageView, options);
    }

    public static void loadLocal(Context context, final int resourceId, final ImageView imageView, RequestOptions options) {
        if (resourceId != 0) {
            imageView.setImageResource(R.mipmap.load_photo_fail);
        }
        if (context == null) {
            context = AppAgent.getApp();
        }
        if (options == null) {
            options = BitmapUtil.options1;
        }
        Glide.with(context)
                .load(resourceId)
                .apply(options)
                .into(imageView);
    }

    public static void loadLocal(final int resourceId, final ImageView imageView, RequestOptions options) {
        loadLocal(null, resourceId, imageView, options);
    }

    public static void loadLocal(final int resourceId, final ImageView imageView) {
        loadLocal(null, resourceId, imageView, null);
    }

    public static void loadLocal(Context context, final int resourceId, final ImageView imageView) {
        loadLocal(context, resourceId, imageView, null);
    }

    public static void loadLocal(final String path, final ImageView imageView) {
        loadLocal(null, path, imageView);
    }

    public static void loadLocal(Context context, final String path, final ImageView imageView) {
        loadLocal(context, path, imageView, null);
    }

    public static void loadLocal(Context context, final String path, final ImageView imageView, RequestOptions options) {
        if (StringUtils.isEmpty(path) || imageView == null) {
            Logger.error("", "loadLocal path is null");
            return;
        }
        final File file = new File(path);
        loadLocal(context, file, imageView, options);
    }

    public static boolean saveImage(Bitmap bitmap, String absPath) {
        return saveImage(bitmap, absPath, 100);
    }

    public static boolean saveImage(Bitmap bitmap, String absPath, int quality) {
        try {
            File outFile = new File(absPath);
            // if (outFile.exists()) {
            //     outFile.delete();
            // }
            // if (!outFile.getParentFile().exists()) {
            //     outFile.getParentFile().mkdirs();
            // }
            // try {
            //     outFile.createNewFile();
            // } catch (IOException ex) {
            //     Logger.error(TAG, "Create file occur an IOException");
            //     return false;
            // }
            FileOutputStream fos = new FileOutputStream(outFile);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            bitmap.compress(Bitmap.CompressFormat.PNG, quality, bos);
            bos.flush();
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
            Logger.error(TAG, "failed to write image content");
            return false;
        }

        return true;
    }

    public static Bitmap compressImage(int maxSize, Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        int options = 90;
        int length = baos.toByteArray().length / 1024;

        if (length > 5000) {
            //重置baos即清空baos
            baos.reset();
            //质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
            image.compress(Bitmap.CompressFormat.JPEG, 10, baos);
        } else if (length > 4000) {
            baos.reset();
            image.compress(Bitmap.CompressFormat.JPEG, 20, baos);
        } else if (length > 3000) {
            baos.reset();
            image.compress(Bitmap.CompressFormat.JPEG, 50, baos);
        } else if (length > 2000) {
            baos.reset();
            image.compress(Bitmap.CompressFormat.JPEG, 70, baos);
        }
        //循环判断如果压缩后图片是否大于1M,大于继续压缩
        while (baos.toByteArray().length / 1024 > maxSize) {
            //重置baos即清空baos
            baos.reset();
            //这里压缩options%，把压缩后的数据存放到baos中
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
            //每次都减少10
            options -= 5;
        }
        //把压缩后的数据baos存放到ByteArrayInputStream中
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        //把ByteArrayInputStream数据生成图片
        return BitmapFactory.decodeStream(isBm, null, null);
    }

    public static Bitmap concatBitmap(Context context, String filePath, Bitmap secondBitmap) {
        if (secondBitmap == null) {
            return null;
        } else {
            int navHeight =
                    SystemUtils.getHeightWithNav(context) - SystemUtils.getHeightWithoutNav(context);
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            options.inPreferredConfig = Bitmap.Config.RGB_565;
            BitmapFactory.decodeFile(filePath, options);
            int width = options.outWidth;
            int height = options.outHeight - navHeight;
            int max = 1048576;

            int sampleSize = 1;
            while (width / sampleSize * height / sampleSize > max) {
                sampleSize *= 2;
            }

            options.inSampleSize = sampleSize;
            options.inJustDecodeBounds = false;
            Bitmap srcBmp = BitmapFactory.decodeFile(filePath, options);
            double bmWidth = 1.0D * (double) secondBitmap.getWidth();
            // 先计算bitmap的宽高，因为bitmap的宽度和屏幕宽度是不一样的，需要按比例拉伸
            double ratio = bmWidth / (double) srcBmp.getWidth();
            int additionalHeight = (int) ((double) secondBitmap.getHeight() / ratio);
            Bitmap scaledBmp = Bitmap.createScaledBitmap(secondBitmap, srcBmp.getWidth(),
                    additionalHeight, false);
            // 到这里图片拉伸完毕
            // 这里开始拼接，画到Canvas上
            Bitmap result = Bitmap.createBitmap(srcBmp.getWidth(),
                    srcBmp.getHeight() - navHeight / sampleSize + additionalHeight,
                    Bitmap.Config.RGB_565);
            Canvas canvas = new Canvas();
            canvas.setBitmap(result);
            canvas.drawBitmap(srcBmp, 0.0F, 0.0F, (Paint) null);
            // 这里需要做个判断，因为一些系统是有导航栏的，所以截图时有导航栏，这里需要把导航栏遮住
            // 计算出导航栏高度，然后draw时往上偏移一段距离
            int displayWidth = SystemUtils.getDisplayWidth((Activity) context);

            double navRatio = 1.0D * (double) displayWidth / (double) srcBmp.getWidth();
            canvas.drawBitmap(scaledBmp, 0.0F,
                    (float) (srcBmp.getHeight() - (int) ((double) navHeight / navRatio)),
                    (Paint) null);
            secondBitmap.recycle();
            return result;
        }
    }

    public final Bitmap file2Bitmap(String filePath) {
        File file = new File(filePath);
        Bitmap bitmap;
        if (file.exists()) {
            bitmap = BitmapFactory.decodeFile(filePath);
        } else {
            Logc.e("", "The file is not exist!");
            bitmap = null;
        }

        return bitmap;
    }

    public static Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        } else {
            Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
                    drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
            return bitmap;
        }
    }
}
